﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HammerMUD.Accounts;
using HammerMUD.Commands;
using HammerMUD.Characters;
using HammerMUD.Races;
using HammerMUD.Professions;
using HammerMUD.Areas;
using HammerMUD.Rooms;
using HammerMUD.Items;
using HammerMUD.NPC;

namespace HammerMUD.System
{
    /// <summary>
    /// This class is the main control class for the MUD framework. The server/client
    /// relationship is handled in a layer abstracted from the framework, but the ProcessLine
    /// call is the main entry point to the framework from a client's perspective. This class
    /// is essential to the smooth operation of the MUD and should only be edited by experienced
    /// programmers
    /// </summary>
    /// <remarks>
    /// WARNING! Advanced programmers only!!
    /// </remarks>
    public class HammerMUD
    {
        /// <summary>
        /// An empty room, used for when there
        /// are no areas/rooms (probably because
        /// of a load failure)
        /// </summary>
        public static Room EmptyRoom;

        public static List<Command> Commands;
        public static List<User> Users;
        public static List<Area> Areas;
        public static SystemInfo SystemInfo;
        public static List<Race> Races;
        public static List<Account> Accounts;
        public static List<Item> Items;
        public static List<Npc> Npcs;

        public HammerMUD()
        {
            HammerMUD.Users = new List<User>();
            HammerMUD.Areas = SystemUtilities.LoadAreas();
            HammerMUD.SystemInfo = SystemUtilities.LoadSystemInfo();
            HammerMUD.Commands = Command.SetUpCommands();
            HammerMUD.Accounts = SystemUtilities.LoadAccounts();
            HammerMUD.Races = SystemUtilities.LoadRaces();
            HammerMUD.Items = SystemUtilities.LoadItems();
            HammerMUD.Npcs = SystemUtilities.LoadNpcs();

            HammerMUD.EmptyRoom = new Room()
            {
                MemberOfArea = null,
                Items = new List<Item>(),
                Name = "Empty Room",
                RoomNumber = -1
            };
        }

        public void FlushUsers()
        {
            foreach (User u in HammerMUD.Users)
            {
                u.Flush();
            }
        }

        public void OnConnect(User user)
        {
            HammerMUD.Users.Add(user);
            user.Send(HammerMUD.SystemInfo.WelcomeMessage);
            user.Prompt("Please enter the account name: ");
        }

        public void Disconnect(User user)
        {
            HammerMUD.Users.Remove(user);
            user.Close();
        }

        /// <summary>
        /// The main entry point for the program from the clients perspective. Essentially,
        /// this is just a big case statement that redirects to different parts of the framework.
        /// In "normal" state, the line is processed in CommandUtilities. So, unless a special
        /// mode needs to be added, this function should be left alone!
        /// </summary>
        /// <param name="line"></param>
        /// <param name="user"></param>
        public void ProcessLine(String line, User user)
        {
            switch (user.CurrentState.Base)
            {
                case BaseState.NewAccount:
                    NewAccountUtilities.ProcessNewAccount(line, user, HammerMUD.Accounts, this);
                    break;
                case BaseState.LogIn:
                    LogInUtilities.ProcessLogin(line, user, HammerMUD.Accounts);
                    break;
                case BaseState.Command:
                    CommandUtilities.ProcessCommand(line, user);
                    break;
                case BaseState.AccountMenu:
                    AccountMenuUtilities.ProcessAccountMenu(line, user, this);
                    break;
                case BaseState.NewCharacter:
                    NewCharacterUtilities.ProcessNewCharacter(line, user, HammerMUD.Races, HammerMUD.Accounts);
                    break;
                default:
                    user.Send("Error!");
                    break;
            }
        }

        internal static void Save()
        {
            SystemUtilities.SaveAccounts(HammerMUD.Accounts);
            SystemUtilities.SaveAreas(HammerMUD.Areas);
            SystemUtilities.SaveRaces(HammerMUD.Races);
            SystemUtilities.SaveItems(HammerMUD.Items);
            SystemUtilities.SaveSystemInfo(HammerMUD.SystemInfo);
            SystemUtilities.SaveNpcs(HammerMUD.Npcs);
        }
    }
}
